<template>
  <div class="app-container">
    <!-- 顶部工具条 -->
    <div class="toolbar">
      <div class="toolbar-title">
        <i class="el-icon-connection"></i> 数据库字段映射工具
      </div>
      <div class="toolbar-buttons">
        <button class="toolbar-btn" @click="refreshData">
          <i class="el-icon-refresh"></i> 刷新数据
        </button>
        <button class="toolbar-btn" @click="addNewTableMapping">
          <i class="el-icon-document-add"></i> 新建映射
        </button>
        <button class="toolbar-btn" @click="autoMapFields">
          <i class="el-icon-copy-document"></i> 自动映射
        </button>
        <div class="divider"></div>
        <button class="toolbar-btn reset-btn" @click="resetAll">
          <i class="el-icon-refresh-left"></i> 重置配置
        </button>
        <button class="toolbar-btn submit-btn" @click="confirmMapping">
          <i class="el-icon-finished"></i> 保存映射
        </button>
      </div>
    </div>

    <!-- 数据库选择行 -->
    <div class="db-selector-row">
      <!-- 源数据库选择 -->
      <div class="db-selector">
        <i class="selector-icon source-icon el-icon-database"></i>
        <el-select
          v-model="selectedSourceDb"
          placeholder="选择源数据库"
          size="medium"
          @change="loadSourceDatabase"
          style="flex: 1;"
        >
          <el-option
            v-for="db in sourceDatabases"
            :key="db.id"
            :label="db.name"
            :value="db.id"
          >
            <div style="display: flex; align-items: center;">
              <i :class="db.icon" style="margin-right: 8px; color: #4286f4;"></i>
              <span>{{ db.name }}</span>
            </div>
          </el-option>
        </el-select>
        <div class="db-info">
          <i class="el-icon-info"></i>
          <span>{{ getSourceDbType() }}</span>
        </div>
      </div>

      <!-- 目标数据库选择 -->
      <div class="db-selector">
        <i class="selector-icon target-icon el-icon-s-promotion"></i>
        <el-select
          v-model="selectedTargetDb"
          placeholder="选择目标数据库"
          size="medium"
          @change="loadTargetDatabase"
          style="flex: 1;"
        >
          <el-option
            v-for="db in targetDatabases"
            :key="db.id"
            :label="db.name"
            :value="db.id"
          >
            <div style="display: flex; align-items: center;">
              <i :class="db.icon" style="margin-right: 8px; color: #43cea2;"></i>
              <span>{{ db.name }}</span>
            </div>
          </el-option>
        </el-select>
        <div class="db-info">
          <i class="el-icon-info"></i>
          <span>{{ getTargetDbType() }}</span>
        </div>
      </div>
    </div>

    <!-- 主内容区 -->
    <div class="main-content">
      <!-- 左: 源数据库 -->
      <div class="source-tree-section">
        <div class="section-header">
          <div>
            <i class="el-icon-folder-opened"></i> 源数据库
          </div>
          <div class="mapped-count">
            已映射: {{ sourceTablesMapped }}
          </div>
        </div>
        <div class="tree-content">
          <el-tree
            ref="sourceTree"
            v-if="sourceDbTreeData.length"
            :data="sourceDbTreeData"
            node-key="id"
            draggable
            :props="treeProps"
            @node-drag-start="onSourceDragStart"
            @node-drag-end="onDragEnd"
            default-expand-all
          >
            <span slot-scope="{ node, data }" class="custom-tree-node">
              <i :class="getIconForNode(data)"></i>
              <span>{{ data.label }}</span>
            </span>
          </el-tree>
          <div v-else class="empty-placeholder">
            <i class="el-icon-data-line"></i>
            <p>请选择源数据库加载</p>
          </div>
        </div>
      </div>

      <!-- 中: 映射区域 -->
      <div class="mapping-center">
        <!-- 表映射行 -->
        <div class="mapping-section">
          <div class="mapping-title">
            <i class="el-icon-set-up"></i> 表映射配置
          </div>
          <div class="mapping-content">
            <div v-if="tableMappings.length > 0"
                 class="mapping-row"
                 :class="{ 'active': tableMappings[0].id === selectedMapping }"
                 @click="selectMapping(tableMappings[0].id)">
              <div class="row-number">1</div>
              <div class="field-box source-field"
                   :class="{ 'drag-over': activeTarget === 'source-table-0' }"
                   @dragover.prevent="handleDragover('source-table', 0)"
                   @dragleave="handleDragleave('source-table', 0)"
                   @drop.prevent="onSourceTableDrop(0, $event)">
                <div class="tags-container">
                  <div v-for="(source, srcIdx) in tableMappings[0].sources" :key="srcIdx" class="tag source-tag">
                    <i :class="source.type === 'table' ? 'table-icon el-icon-s-grid' : 'view-icon el-icon-s-promotion'"></i>
                    <span>{{ source.label }}</span>
                    <button class="remove-source-btn" @click.stop="removeSourceFromMapping(tableMappings[0].id, srcIdx)">
                      <i class="el-icon-close"></i>
                    </button>
                    <!-- 新增：关联图标（仅在非最后一个表后显示） -->
                    <el-tooltip v-if="srcIdx < tableMappings[0].sources.length - 1"
                                :content="getJoinFieldsTip(srcIdx, srcIdx+1)"
                                placement="top">
                      <i class="join-icon el-icon-link"
                         :class="{'has-join': hasJoinBetween(srcIdx, srcIdx+1)}"></i>
                    </el-tooltip>
                  </div>
                  <div v-if="!tableMappings[0].sources.length" class="empty-placeholder">
                    拖拽源表或视图
                  </div>
                </div>
              </div>

              <button class="remove-btn" @click.stop="removeMapping(tableMappings[0].id)">
                <i class="el-icon-delete"></i>
              </button>
            </div>

            <!-- 新增：Join关系配置面板 -->
            <div v-if="tableMappings[0] && tableMappings[0].sources.length > 1" class="join-config-section">
              <div class="join-config-title">
                <i class="el-icon-link"></i> 表关联关系配置
              </div>

              <div class="join-config-content">
                <div v-for="(join, index) in tableMappings[0].joinConfig" :key="index" class="join-config-item">
                  <div class="table-selectors">
                    <el-select v-model="join.leftTableIndex" placeholder="选择左侧表" size="small">
                      <el-option
                        v-for="(table, idx) in tableMappings[0].sources"
                        :key="idx"
                        :label="table.label"
                        :value="idx"
                      />
                    </el-select>

                    <el-select v-model="join.type" placeholder="JOIN类型" size="small" class="join-type-select">
                      <el-option label="INNER JOIN" value="INNER" />
                      <el-option label="LEFT JOIN" value="LEFT" />
                      <el-option label="RIGHT JOIN" value="RIGHT" />
                      <el-option label="FULL JOIN" value="FULL" />
                    </el-select>

                    <el-select v-model="join.rightTableIndex" placeholder="选择右侧表" size="small">
                      <el-option
                        v-for="(table, idx) in tableMappings[0].sources"
                        :key="idx"
                        :label="table.label"
                        :value="idx"
                      />
                    </el-select>
                  </div>

                  <div class="field-selectors">
                    <el-select
                      v-model="join.leftField"
                      placeholder="左侧表字段"
                      size="small"
                      :disabled="!join.leftTableIndex"
                    >
                      <el-option
                        v-for="field in getTableFields(tableMappings[0].sources[join.leftTableIndex])"
                        :key="field.id"
                        :label="field.label"
                        :value="field.id"
                      />
                    </el-select>

                    <span class="join-equal">=</span>

                    <el-select
                      v-model="join.rightField"
                      placeholder="右侧表字段"
                      size="small"
                      :disabled="!join.rightTableIndex"
                    >
                      <el-option
                        v-for="field in getTableFields(tableMappings[0].sources[join.rightTableIndex])"
                        :key="field.id"
                        :label="field.label"
                        :value="field.id"
                      />
                    </el-select>

                    <button class="remove-join-btn" @click="removeJoinConfig(index)">
                      <i class="el-icon-delete"></i>
                    </button>
                  </div>
                </div>

                <button class="add-join-btn" @click="addJoinConfig">
                  <i class="el-icon-plus"></i> 添加关联关系
                </button>
              </div>
            </div>
          </div>
        </div>

        <!-- 字段映射行 -->
        <div v-if="selectedMapping" class="field-mapping-section">
          <div class="section-header">
            <div>
              <i class="el-icon-s-operation"></i>
              <span class="target-table-name">{{ getSelectedTargetTableName() }}</span>
              字段映射配置
            </div>
            <div class="mapped-count">
              字段映射: {{ sourceFieldsMapped }} / {{ targetFieldsMapped }}
            </div>
          </div>

          <div class="field-mapping-container">
            <!-- 字段映射中心区域 -->
            <div class="field-mapping-center">
              <div class="field-mapping-content">
                <div v-for="(mapping, index) in fieldMappings"
                     :key="mapping.id"
                     class="field-mapping-item">
                  <div class="field-box source-field"
                       :class="{ 'drag-over': activeTarget === 'source-field-' + index }"
                       @dragover.prevent="handleDragover('source-field', index)"
                       @dragleave="handleDragleave('source-field', index)"
                       @drop.prevent="onSourceFieldDrop(index, $event)">
                    <div>
                      <div v-if="mapping.source" class="tag source-tag">
                        <i class="el-icon-document"></i>
                        <span>{{ mapping.source.label }}</span>
                        <span class="field-type-label">{{ mapping.source.type }}</span>
                        <div class="field-status-icon" :class="getFieldStatusClass(mapping.source.type, mapping.target ? mapping.target.type : '')">
                          <i :class="getFieldStatusIcon(mapping.source.type, mapping.target ? mapping.target.type : '')"></i>
                        </div>
                      </div>
                      <div v-else class="empty-placeholder">
                        拖拽源字段
                      </div>
                    </div>
                  </div>

                  <div class="arrow-icon">
                    <i class="el-icon-right"></i>
                  </div>

                  <div class="field-box target-field"
                       :class="{ 'drag-over': activeTarget === 'target-field-' + index }"
                       @dragover.prevent="handleDragover('target-field', index)"
                       @dragleave="handleDragleave('target-field', index)"
                       @drop.prevent="onTargetFieldDrop(index, $event)">
                    <div>
                      <div v-if="mapping.target" class="tag target-tag">
                        <i class="el-icon-document"></i>
                        <span>{{ mapping.target.label }}</span>
                        <span class="field-type-label">{{ mapping.target.type }}</span>
                      </div>
                      <div v-else class="empty-placeholder">
                        拖拽目标字段
                      </div>
                    </div>
                  </div>

                  <button class="remove-btn" @click="removeFieldMapping(index)">
                    <i class="el-icon-delete"></i>
                  </button>
                </div>

                <!-- 新增字段映射模板行 -->
                <div class="template-row" @click="addNewFieldMapping">
                  <i class="el-icon-plus"></i>
                  <p>点击添加新映射</p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 右: 目标数据库 -->
      <div class="target-tree-section">
        <div class="section-header">
          <div>
            <i class="el-icon-folder-opened"></i> 目标数据库
          </div>
          <div class="mapped-count">
            已映射: {{ targetTablesMapped }}
          </div>
        </div>
        <div class="tree-content">
          <el-tree
            ref="targetTree"
            v-if="targetDbTreeData.length"
            :data="targetDbTreeData"
            node-key="id"
            draggable
            :props="treeProps"
            @node-click="onTargetNodeClick"
            @node-drag-start="onTargetDragStart"
            @node-drag-end="onDragEnd"
            default-expand-all
          >
            <span slot-scope="{ node, data }" class="custom-tree-node">
              <i :class="getIconForNode(data)"></i>
              <span>{{ data.label }}</span>
            </span>
          </el-tree>
          <div v-else class="empty-placeholder">
            <i class="el-icon-data-line"></i>
            <p>请选择目标数据库加载</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "DatabaseFieldMapper",
  data() {
    return {
      // 树配置
      treeProps: {
        label: 'label',
        children: 'children'
      },

      // 数据库选择相关
      sourceDatabases: [
        { id: 'db1', name: '生产数据库', type: 'MySQL', icon: 'el-icon-s-data' },
        { id: 'db2', name: '测试数据库', type: 'SQL Server', icon: 'el-icon-s-data' },
        { id: 'db3', name: '备份数据库', type: 'Oracle', icon: 'el-icon-s-data' },
        { id: 'db4', name: '归档数据库', type: 'PostgreSQL', icon: 'el-icon-s-data' }
      ],
      targetDatabases: [
        { id: 'db5', name: '数据仓库', type: 'Greenplum', icon: 'el-icon-s-claim' },
        { id: 'db6', name: '分析平台', type: 'Snowflake', icon: 'el-icon-s-marketing' },
        { id: 'db7', name: '报表系统', type: 'Redshift', icon: 'el-icon-s-marketing' },
        { id: 'db8', name: '主数据系统', type: 'MySQL', icon: 'el-icon-s-data' }
      ],
      selectedSourceDb: 'db1',
      selectedTargetDb: 'db5',

      // 树数据
      sourceDbTreeData: [],
      targetDbTreeData: [],

      // 表映射
      tableMappings: [],
      selectedMapping: null,

      // 字段相关
      targetFieldTreeData: [],
      fieldMappings: [],

      // 当前拖拽信息
      currentDragNode: null,
      dragType: null,
      activeTarget: null,

      // 拖拽的字段数据
      draggedField: null
    };
  },
  computed: {
    // 源表已映射数量
    sourceTablesMapped() {
      return this.tableMappings.reduce((count, m) => count + m.sources.length, 0);
    },
    // 目标表已映射数量
    targetTablesMapped() {
      return this.tableMappings.filter(m => m.target).length;
    },
    // 源字段已映射数量
    sourceFieldsMapped() {
      return this.fieldMappings.filter(m => m.source).length;
    },
    // 目标字段已映射数量
    targetFieldsMapped() {
      return this.fieldMappings.filter(m => m.target).length;
    },
    // 当前选中的表映射
    selectedTableMapping() {
      return this.tableMappings.find(m => m.id === this.selectedMapping);
    }
  },
  methods: {
    // 获取数据库类型
    getSourceDbType() {
      const db = this.sourceDatabases.find(d => d.id === this.selectedSourceDb);
      return db ? db.type : '未选择';
    },

    getTargetDbType() {
      const db = this.targetDatabases.find(d => d.id === this.selectedTargetDb);
      return db ? db.type : '未选择';
    },

    // 获取节点图标
    getIconForNode(data) {
      switch (data.type) {
        case 'table': return 'table-icon el-icon-s-grid';
        case 'view': return 'view-icon el-icon-s-promotion';
        case 'group': return 'folder-icon el-icon-folder';
        case 'column': return 'column-icon el-icon-document';
        default: return 'el-icon-document';
      }
    },

    // 刷新数据
    refreshData() {
      this.$message.success('数据库已刷新');
      this.loadSourceDatabase();
      this.loadTargetDatabase();
    },

    // 自动映射字段
    autoMapFields() {
      if (!this.selectedMapping) {
        this.$message.warning('请先选择表映射');
        return;
      }

      // 直接从源表获取字段
      const sourceTable = this.selectedTableMapping.sources[0];
      if (!sourceTable || !sourceTable.columns) {
        this.$message.warning('请先选择源表');
        return;
      }

      let mappedCount = 0;
      this.fieldMappings = [];

      // 修改：直接从源表获取字段
      for (const sourceField of sourceTable.columns) {
        const targetField = this.targetFieldTreeData.find(
          f => f.label.toLowerCase() === sourceField.label.toLowerCase()
        );

        if (targetField) {
          this.fieldMappings.push({
            id: this.generateId(),
            source: { ...sourceField },
            target: { ...targetField }
          });
          mappedCount++;
        }
      }

      if (mappedCount > 0) {
        this.$message.success(`自动映射了 ${mappedCount} 个字段`);
      } else {
        this.$message.warning('未找到匹配的字段');
      }
    },

    // 生成ID
    generateId() {
      return Date.now();
    },

    // 加载源数据库
    loadSourceDatabase() {
      // 生成源数据库树数据
      this.sourceDbTreeData = [{
        id: 'root1',
        label: '源数据库',
        type: 'group',
        children: [
          {
            id: 'src-group1',
            label: '默认分组',
            type: 'group',
            children: [
              {
                id: 'src-table1',
                label: '用户表',
                type: 'table',
                columns: this.generateColumns(5, '用户表'),
                fieldCount: 5,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(5, '用户表').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type // 保留原始数据类型
                }))
              },
              {
                id: 'src-table2',
                label: '订单表',
                type: 'table',
                columns: this.generateColumns(6, '订单表'),
                fieldCount: 6,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(6, '订单表').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              }
            ]
          },
          {
            id: 'src-group2',
            label: '业务分组',
            type: 'group',
            children: [
              {
                id: 'src-table3',
                label: '产品表',
                type: 'table',
                columns: this.generateColumns(5, '产品表'),
                fieldCount: 5,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(5, '产品表').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              },
              {
                id: 'src-table4',
                label: '库存表',
                type: 'table',
                columns: this.generateColumns(4, '库存表'),
                fieldCount: 4,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(4, '库存表').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              }
            ]
          },
          {
            id: 'src-views',
            label: '视图',
            type: 'group',
            children: [
              {
                id: 'src-view1',
                label: '用户订单视图',
                type: 'view',
                columns: this.generateColumns(5, '用户订单视图'),
                fieldCount: 5,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(5, '用户订单视图').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              }
            ]
          }
        ]
      }];
    },

    // 加载目标数据库
    loadTargetDatabase() {
      // 生成目标数据库树数据
      this.targetDbTreeData = [{
        id: 'root2',
        label: '目标数据库',
        type: 'group',
        children: [
          {
            id: 'tgt-group1',
            label: '默认分组',
            type: 'group',
            children: [
              {
                id: 'tgt-table1',
                label: '客户信息',
                type: 'table',
                columns: this.generateColumns(6, '客户信息'),
                fieldCount: 6,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(6, '客户信息').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              },
              {
                id: 'tgt-table2',
                label: '交易记录',
                type: 'table',
                columns: this.generateColumns(8, '交易记录'),
                fieldCount: 8,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(8, '交易记录').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              }
            ]
          },
          {
            id: 'tgt-group2',
            label: '分析分组',
            type: 'group',
            children: [
              {
                id: 'tgt-table3',
                label: '销售分析',
                type: 'table',
                columns: this.generateColumns(7, '销售分析'),
                fieldCount: 7,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(7, '销售分析').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              },
              {
                id: 'tgt-table4',
                label: '库存分析',
                type: 'table',
                columns: this.generateColumns(5, '库存分析'),
                fieldCount: 5,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(5, '库存分析').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              }
            ]
          },
          {
            id: 'tgt-views',
            label: '报表视图',
            type: 'group',
            children: [
              {
                id: 'tgt-view1',
                label: '月度报表',
                type: 'view',
                columns: this.generateColumns(6, '月度报表'),
                fieldCount: 6,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(6, '月度报表').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              },
              {
                id: 'tgt-view2',
                label: '年度汇总',
                type: 'view',
                columns: this.generateColumns(6, '年度汇总'),
                fieldCount: 6,
                // 新增：添加列数据作为子节点
                children: this.generateColumns(6, '年度汇总').map(col => ({
                  id: col.id,
                  label: col.label,
                  type: 'column',
                  dataType: col.type
                }))
              }
            ]
          }
        ]
      }];
    },

    // 生成列数据
    generateColumns(count, prefix) {
      const columns = [];
      const types = ['VARCHAR(50)', 'INT', 'DATETIME', 'DECIMAL(10,2)', 'BOOLEAN'];

      for (let i = 1; i <= count; i++) {
        const typeIndex = Math.floor(Math.random() * types.length);
        columns.push({
          id: `${prefix}_col${i}`,
          label: `${prefix}列${i}`,
          type: types[typeIndex]
        });
      }
      return columns;
    },

    // 源树开始拖拽（表或视图）
    onSourceDragStart(node) {
      if (node.data.type === 'table' || node.data.type === 'view') {
        this.currentDragNode = node.data;
        this.dragType = 'source-table';
      } else if (node.data.type === 'column') {
        // 修改：使用dataType作为字段数据类型
        this.draggedField = {
          ...node.data,
          type: node.data.dataType // 保留原始数据类型
        };
        this.dragType = 'source-field';
      }
    },

    // 目标树开始拖拽（表或视图）
    onTargetDragStart(node) {
      if (node.data.type === 'table' || node.data.type === 'view') {
        this.currentDragNode = node.data;
        this.dragType = 'target-table';
      } else if (node.data.type === 'column') {
        // 修改：使用dataType作为字段数据类型
        this.draggedField = {
          ...node.data,
          type: node.data.dataType // 保留原始数据类型
        };
        this.dragType = 'target-field';
      }
    },

    // 字段拖拽开始 - 移除目标字段拖拽处理
    onFieldDragStart(type, field) {
      // 只保留源字段的拖拽功能
      if (type === 'source') {
        this.draggedField = field;
        this.dragType = `${type}-field`;
      }
    },

    // 拖拽结束处理
    onDragEnd() {
      this.currentDragNode = null;
      this.dragType = null;
      this.activeTarget = null;
      this.draggedField = null;
    },

    // 在投放目标上悬停
    handleDragover(targetId, index) {
      this.activeTarget = `${targetId}-${index}`;
    },

    // 离开投放目标区域
    handleDragleave(targetId, index) {
      if (this.activeTarget === `${targetId}-${index}`) {
        this.activeTarget = null;
      }
    },

    // 在源表区域投放
    onSourceTableDrop(index) {
      if (!this.currentDragNode || this.dragType !== 'source-table') return;

      const dragNode = this.currentDragNode;

      // 如果拖到已有映射行
      if (index < this.tableMappings.length) {
        // 添加新源表到现有映射
        this.tableMappings[index].sources.push({ ...dragNode });

        // 如果这是映射中的第一个源表且映射已选中，加载字段
        if (this.tableMappings[index].id === this.selectedMapping &&
            this.tableMappings[index].sources.length === 1) {
          this.loadSourceFields(dragNode);
        }
      }
      // 如果拖到模板行，创建新行
      else {
        this.addNewTableMapping([dragNode]);
      }

      this.removeNodeFromTree(this.sourceDbTreeData, dragNode.id);
      this.onDragEnd();
    },

    // 在目标表区域投放
    onTargetTableDrop(index) {
      if (!this.currentDragNode || this.dragType !== 'target-table') return;
      const dragNode = this.currentDragNode;

      if (index < this.tableMappings.length) {
        if (this.tableMappings[index].target) {
          this.addBackToTree(this.tableMappings[index].target, 'target');
        }

        this.tableMappings[index].target = { ...dragNode };

        if (this.tableMappings[index].id === this.selectedMapping) {
          this.loadTargetFields(dragNode);
        }
      }
      // 如果拖到模板行，创建新行
      else {
        this.addNewTableMapping(null, dragNode);
      }

      this.removeNodeFromTree(this.targetDbTreeData, dragNode.id);
      this.onDragEnd();
    },

    // 在源字段区域投放
    onSourceFieldDrop(index) {
      if (!this.draggedField || this.dragType !== 'source-field') return;
      const field = this.draggedField;

      if (index < this.fieldMappings.length) {
        if (this.fieldMappings[index].source) {
          // 删除：不再放回源字段列表
        }

        this.fieldMappings[index].source = { ...field };
      }
      // 如果拖到模板行，创建新行
      else {
        this.addNewFieldMapping(field);
      }

      // 从树中移除该字段节点
      this.removeNodeFromTree(this.sourceDbTreeData, field.id);
      this.onDragEnd();
    },

    // 在目标字段区域投放 - 移除相关功能
    // onTargetFieldDrop(index) {
    //   if (!this.draggedField || this.dragType !== 'target-field') return;
    //   const field = this.draggedField;

    //   if (index < this.fieldMappings.length) {
    //     if (this.fieldMappings[index].target) {
    //       this.targetFieldTreeData.push({...this.fieldMappings[index].target});
    //     }

    //     this.fieldMappings[index].target = { ...field };
    //   }
    //   // 如果拖到模板行，创建新行
    //   else {
    //     this.addNewFieldMapping(null, field);
    //   }

    //   this.removeFromFieldList(this.targetFieldTreeData, field.id);
    //   this.onDragEnd();
    // },

    // 从树中移除节点
    removeNodeFromTree(treeData, nodeId) {
      const findAndRemove = (nodes) => {
        for (let i = 0; i < nodes.length; i++) {
          if (nodes[i].id === nodeId) {
            nodes.splice(i, 1);
            return true;
          }
          if (nodes[i].children && nodes[i].children.length) {
            if (findAndRemove(nodes[i].children)) {
              return true;
            }
          }
        }
        return false;
      };

      findAndRemove(treeData);
    },

    // 将节点加回树中
    addBackToTree(node, dbType) {
      if (dbType === 'source') {
        // 找到原位置的分组
        const groupId = node.type === 'table' ? 'src-group1' : 'src-views';
        const group = this.findGroup(this.sourceDbTreeData, groupId);

        if (group) {
          if (!group.children) group.children = [];
          group.children.push({...node});
        }
      } else {
        // 目标数据库
        const groupId = node.type === 'table' ? 'tgt-group1' : 'tgt-views';
        const group = this.findGroup(this.targetDbTreeData, groupId);

        if (group) {
          if (!group.children) group.children = [];
          group.children.push({...node});
        }
      }
    },

    // 从字段列表中移除字段
    removeFromFieldList(fieldList, fieldId) {
      const index = fieldList.findIndex(f => f.id === fieldId);
      if (index !== -1) {
        fieldList.splice(index, 1);
      }
    },

    // 查找组
    findGroup(treeData, groupId) {
      const findInNodes = (nodes) => {
        for (const node of nodes) {
          if (node.id === groupId) {
            return node;
          }
          if (node.children && node.children.length) {
            const found = findInNodes(node.children);
            if (found) return found;
          }
        }
        return null;
      };

      return findInNodes(treeData);
    },

    // 添加新表映射 - 修改：只允许创建一条映射
    addNewTableMapping(sources = []) {
      // 如果已存在映射，则清空现有映射
      if (this.tableMappings.length > 0) {
        // 清空前将表节点放回树中
        const mapping = this.tableMappings[0];
        mapping.sources.forEach(source => {
          this.addBackToTree(source, 'source');
        });
        if (mapping.target) {
          this.addBackToTree(mapping.target, 'target');
        }
      }

      const newId = this.generateId();
      this.tableMappings = [{
        id: newId,
        sources: sources.map(src => ({ ...src })),
        target: null,
        joinConfig: [] // 初始化join配置
      }];

      this.selectMapping(newId);
    },

    // 添加新字段映射
    addNewFieldMapping(source, target) {
      const newField = {
        id: this.generateId(),
        source: source ? { ...source } : null,
        target: target ? { ...target } : null
      };

      this.fieldMappings.push(newField);
    },

    // 删除表映射 - 修改：保留映射行但清空内容
    removeMapping(mappingId) {
      const mapping = this.tableMappings.find(m => m.id === mappingId);
      if (!mapping) return;

      // 将表节点放回树中
      mapping.sources.forEach(source => {
        this.addBackToTree(source, 'source');
      });
      if (mapping.target) {
        this.addBackToTree(mapping.target, 'target');
      }

      // 清空映射内容
      mapping.sources = [];
      mapping.target = null;

      // 清空字段映射
      this.fieldMappings = [];
    },

    // 删除字段映射
    removeFieldMapping(index) {
      const mapping = this.fieldMappings[index];

      // 将源字段节点放回树中
      if (mapping.source) {
        this.addColumnBackToTree(mapping.source);
      }
      // 删除目标字段回加逻辑
      if (mapping.target) {
        this.targetFieldTreeData.push({...mapping.target});
      }

      // 删除字段映射
      this.fieldMappings.splice(index, 1);
    },
    
    // 新增：将字段节点加回树中
    addColumnBackToTree(field) {
      // 找到原位置的表节点
      const tableNode = this.findTreeNode(this.sourceDbTreeData, field.parentId);
      if (tableNode && tableNode.children) {
        tableNode.children.push({
          id: field.id,
          label: field.label,
          type: 'column',
          dataType: field.type,
          parentId: tableNode.id
        });
      }
    },
    
    // 新增：查找树节点
    findTreeNode(treeData, nodeId) {
      const findInNodes = (nodes) => {
        for (const node of nodes) {
          if (node.id === nodeId) {
            return node;
          }
          if (node.children && node.children.length) {
            const found = findInNodes(node.children);
            if (found) return found;
          }
        }
        return null;
      };

      return findInNodes(treeData);
    },

    // 选择映射行
    selectMapping(mappingId) {
      this.selectedMapping = mappingId;
      const mapping = this.tableMappings.find(m => m.id === mappingId);

      if (mapping && mapping.target) {
        this.loadTargetFields(mapping.target);
      } else {
        this.targetFieldTreeData = [];
      }

      // 加载字段映射
      if (mapping && mapping.fieldMappings) {
        this.fieldMappings = [...mapping.fieldMappings];
      } else {
        this.fieldMappings = [];
      }
    },

    // 加载目标表字段 - 移除相关功能
    loadTargetFields(table) {
      // 创建字段数据
      this.targetFieldTreeData = Array.isArray(table.columns) ?
        [...table.columns] :
        this.generateColumns(5, 'TGT');
    },

    // 获取字段状态类
    getFieldStatusClass(sourceType, targetType) {
      if (!sourceType || !targetType) return 'field-status-error';

      const srcBaseType = sourceType.replace(/$.*$/g, '').toUpperCase().trim();
      const tgtBaseType = targetType.replace(/$.*$/g, '').toUpperCase().trim();

      if (srcBaseType === tgtBaseType) return 'field-status-good';
      return 'field-status-warning';
    },

    // 获取字段状态图标
    getFieldStatusIcon(sourceType, targetType) {
      const statusClass = this.getFieldStatusClass(sourceType, targetType);

      if (statusClass === 'field-status-good') return 'el-icon-success';
      if (statusClass === 'field-status-warning') return 'el-icon-warning';
      return 'el-icon-error';
    },

    // 获取选中的源表名称
    getSelectedSourceTableName() {
      if (!this.selectedMapping) return '未选择';

      const mapping = this.tableMappings.find(m => m.id === this.selectedMapping);
      return mapping && mapping.source ? mapping.source.label : '未选择';
    },

    // 获取选中的目标表名称
    getSelectedTargetTableName() {
      if (!this.selectedMapping) return '未选择';

      const mapping = this.tableMappings.find(m => m.id === this.selectedMapping);
      return mapping && mapping.target ? mapping.target.label : '未选择';
    },

    // 重置所有配置
    resetAll() {
      this.$confirm('确定要重置所有配置吗？所有映射数据将被清空', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 将所有表节点放回树中
        for (const mapping of this.tableMappings) {
          if (mapping.source) this.addBackToTree(mapping.source, 'source');
          if (mapping.target) this.addBackToTree(mapping.target, 'target');
        }

        this.tableMappings = [];
        this.fieldMappings = [];
        this.selectedMapping = null;
        this.$message.success('配置已重置');

        // 重新加载数据库
        this.loadSourceDatabase();
        this.loadTargetDatabase();
      });
    },

    // 保存映射
    confirmMapping() {
      // 收集表映射数据
      const mappings = this.tableMappings.map(mapping => ({
        source: mapping.source ? {
          id: mapping.source.id,
          name: mapping.source.label,
          type: mapping.source.type
        } : null,
        target: mapping.target ? {
          id: mapping.target.id,
          name: mapping.target.label,
          type: mapping.target.type
        } : null,
        fieldMappings: (mapping.fieldMappings || [])
          .filter(f => f.source && f.target)
          .map(f => ({
            source: {
              id: f.source.id,
              name: f.source.label,
              type: f.source.type
            },
            target: {
              id: f.target.id,
              name: f.target.label,
              type: f.target.type
            }
          }))
      }));

      if (mappings.length === 0) {
        this.$message.warning('请先创建表映射关系');
        return;
      }

      // 计算映射完成度
      const tableCount = mappings.length;
      const fieldCount = mappings.reduce((total, m) => total + (m.fieldMappings ? m.fieldMappings.length : 0), 0);

      this.$notify({
        title: '映射已保存',
        message: `成功保存 ${tableCount} 张表的映射关系<br>包含 ${fieldCount} 个字段映射`,
        dangerouslyUseHTMLString: true,
        type: 'success',
        duration: 5000
      });

      console.log('保存的映射配置:', mappings);
    },

    // 新增：目标树节点点击处理
    onTargetNodeClick(data, node) {
      if (data.type === 'table' || data.type === 'view') {
        if (!this.selectedMapping) {
          this.addNewTableMapping(null, data);
          return;
        }

        const mappingIndex = this.tableMappings.findIndex(m => m.id === this.selectedMapping);
        if (mappingIndex !== -1) {
          const mapping = this.tableMappings[mappingIndex];

          if (mapping.target) {
            this.addBackToTree(mapping.target, 'target');
          }

          mapping.target = { ...data };
          this.removeNodeFromTree(this.targetDbTreeData, data.id);
          this.loadTargetFields(data);

          // 新增：自动创建字段映射
          this.fieldMappings = []; // 清空现有字段映射
          const targetFields = [...this.targetFieldTreeData]; // 复制目标字段
          this.targetFieldTreeData = []; // 清空目标字段列表

          // 为每个目标字段创建映射条目
          targetFields.forEach(field => {
            this.fieldMappings.push({
              id: this.generateId(),
              source: null,
              target: { ...field }
            });
          });
        }
      }
    },

    // 从映射中移除源表
    removeSourceFromMapping(mappingId, sourceIndex) {
      const mapping = this.tableMappings.find(m => m.id === mappingId);
      if (mapping && mapping.sources[sourceIndex]) {
        // 将表节点放回树中
        this.addBackToTree(mapping.sources[sourceIndex], 'source');
        mapping.sources.splice(sourceIndex, 1);

        // 如果移除的是当前选中的源表且映射已选中，更新字段
        if (this.selectedMapping === mappingId) {
          this.loadSourceFields();
        }
      }

      // 清理相关join配置
      if (this.tableMappings[0] && this.tableMappings[0].joinConfig) {
        this.tableMappings[0].joinConfig = this.tableMappings[0].joinConfig.filter(join =>
          join.leftTableIndex !== sourceIndex && join.rightTableIndex !== sourceIndex
        );
      }
    },

    // 新增：检查两个表之间是否存在关联
    hasJoinBetween(leftIdx, rightIdx) {
      if (!this.tableMappings[0] || !this.tableMappings[0].joinConfig) return false;
      return this.tableMappings[0].joinConfig.some(join =>
        (join.leftTableIndex === leftIdx && join.rightTableIndex === rightIdx) ||
        (join.leftTableIndex === rightIdx && join.rightTableIndex === leftIdx)
      );
    },

    // 新增：获取两个表之间的关联字段提示
    getJoinFieldsTip(leftIdx, rightIdx) {
      if (!this.tableMappings[0] || !this.tableMappings[0].joinConfig) return "未配置关联关系";

      const join = this.tableMappings[0].joinConfig.find(j =>
        (j.leftTableIndex === leftIdx && j.rightTableIndex === rightIdx) ||
        (j.leftTableIndex === rightIdx && j.rightTableIndex === leftIdx)
      );

      if (!join) return "未配置关联关系";

      const leftTable = this.tableMappings[0].sources[join.leftTableIndex];
      const rightTable = this.tableMappings[0].sources[join.rightTableIndex];

      let leftField = "未知字段";
      if (leftTable && leftTable.columns) {
        const field = leftTable.columns.find(f => f.id === join.leftField);
        if (field) leftField = field.label;
      }

      let rightField = "未知字段";
      if (rightTable && rightTable.columns) {
        const field = rightTable.columns.find(f => f.id === join.rightField);
        if (field) rightField = field.label;
      }

      return `${leftField} = ${rightField}`;
    },

    // 新增：添加join配置
    addJoinConfig() {
      if (!this.tableMappings.length) return;

      const mapping = this.tableMappings[0];
      if (!mapping.joinConfig) {
        this.$set(mapping, 'joinConfig', []);
      }

      mapping.joinConfig.push({
        leftTableIndex: null,
        rightTableIndex: null,
        type: 'INNER',
        leftField: null,
        rightField: null
      });
    },

    // 新增：删除join配置
    removeJoinConfig(index) {
      if (this.tableMappings[0] && this.tableMappings[0].joinConfig) {
        this.tableMappings[0].joinConfig.splice(index, 1);
      }
    },

    // 新增：获取表字段
    getTableFields(table) {
      return (table && table.columns) || [];
    }
  },
  mounted() {
    // 初始加载数据
    this.loadSourceDatabase();
    this.loadTargetDatabase();

    // 添加初始映射
    this.addNewTableMapping();
  }
}
</script>

<style scoped>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}

body {
  background-color: #f5f7fa;
  overflow: hidden;
}

.app-container {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: white;
  overflow: hidden;
}

/* 顶部工具条 */
.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: linear-gradient(135deg, #3a7bd5 0%, #1a2980 100%);
  color: white;
  padding: 12px 30px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  z-index: 10;
  flex-shrink: 0;
}

.toolbar-title {
  display: flex;
  align-items: center;
  font-size: 1.5rem;
  font-weight: 500;
  z-index: 1;
  letter-spacing: 1px;
}

.toolbar-title i {
  margin-right: 12px;
  font-size: 1.6rem;
}

.toolbar-buttons {
  display: flex;
  gap: 12px;
}

.toolbar-btn {
  padding: 10px 20px;
  font-size: 0.95rem;
  font-weight: 500;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s;
  cursor: pointer;
  border: none;
  background: rgba(255, 255, 255, 0.15);
  color: white;
}

.toolbar-btn:hover {
  background: rgba(255, 255, 255, 0.25);
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.toolbar-btn i {
  margin-right: 8px;
  font-size: 1.1rem;
}

.reset-btn {
  background: linear-gradient(135deg, #ff7b54 0%, #ff5252 100%);
}

.submit-btn {
  background: linear-gradient(135deg, #43cea2 0%, #3498db 100%);
}

.reset-btn:hover, .submit-btn:hover {
  box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}

/* 数据库选择行 */
.db-selector-row {
  background: linear-gradient(to right, #f0f8ff, #e6f7ff);
  border-bottom: 1px solid #d1e8ff;
  padding: 15px 30px;
  display: flex;
  flex-wrap: wrap;
  gap: 25px;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 4px rgba(0, 105, 210, 0.1);
  flex-shrink: 0;
}

.db-selector {
  display: flex;
  align-items: center;
  background: white;
  border-radius: 10px;
  padding: 8px 15px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.08);
  border: 1px solid #e1e8f0;
  flex: 1;
  min-width: 480px;
  transition: all 0.3s ease;
}

.db-selector:hover {
  box-shadow: 0 4px 15px rgba(66, 134, 244, 0.15);
  transform: translateY(-2px);
}

.selector-icon {
  font-size: 1.4rem;
  margin-right: 12px;
  flex-shrink: 0;
}

.source-icon {
  color: #4286f4;
}

.target-icon {
  color: #43cea2;
}

.db-selector .el-select {
  flex: 1;
}

.db-info {
  display: flex;
  align-items: center;
  margin-left: 15px;
  flex-shrink: 0;
  background: #f8fafc;
  border-radius: 4px;
  padding: 0 12px;
  font-size: 0.9rem;
  color: #5c6b80;
  height: 30px;
  min-width: 100px;
  transition: all 0.3s;
}

.db-info:hover {
  background: #e3f2fd;
  color: #1a2980;
}

.db-info i {
  margin-right: 6px;
}

/* 主内容区 */
.main-content {
  display: flex;
  flex: 1;
  overflow: hidden;
  background: #f0f4f8;
}

/* 左/右树区域 */
.source-tree-section, .target-tree-section {
  width: 20%; /* 增加宽度比例 */
  display: flex;
  flex-direction: column;
  border: 1px solid #eaeaea;
  background: white;
  border-radius: 8px;
  margin: 10px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}

/* 中: 映射区域 */
.mapping-center {
  width: 60%; /* 增加宽度比例 */
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #f8fafc;
}

/* 源表标签容器 */
.tags-container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center; /* 垂直居中 */
}

/* 源表标签 */
.tag.source-tag {
  display: flex;
  align-items: center;
  position: relative;
}

/* 源表删除按钮 */
.remove-source-btn {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);
  background: none;
  border: none;
  color: #ff6b6b;
  cursor: pointer;
  padding: 2px;
  font-size: 12px;
}

.remove-source-btn:hover {
  color: #ff5252;
}

/* 树区域 */
.section-header {
  background: linear-gradient(to right, #4286f4, #3a7bd5);
  color: white;
  padding: 12px 15px;
  font-size: 1.05rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  border-radius: 6px 6px 0 0;
}

.mapped-count {
  background: rgba(255, 255, 255, 0.3);
  border-radius: 20px;
  padding: 3px 12px;
  font-size: 0.85rem;
  font-weight: bold;
}

.section-header i {
  margin-right: 10px;
}

.tree-content {
  flex: 1;
  overflow: auto;
  padding: 12px;
  position: relative;
}

.custom-tree-node {
  display: flex;
  align-items: center;
  padding: 5px 0;
}

.custom-tree-node i {
  margin-right: 8px;
}

.table-icon {
  color: #4286f4;
}

.view-icon {
  color: #43cea2;
}

.folder-icon {
  color: #ffb74d;
}

.column-icon {
  color: #5c6b80;
}

.empty-placeholder {
  text-align: center;
  color: #999;
  padding: 30px 0;
}

.empty-placeholder i {
  font-size: 2.5rem;
  margin-bottom: 15px;
  color: #d1e0e9;
}

.empty-placeholder p {
  margin-top: 10px;
}

/* 表映射区域 */
.mapping-section {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  margin: 10px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.05);
  border: 1px solid #eaeaea;
}

.mapping-title {
  text-align: center;
  font-size: 1.15rem;
  padding: 12px;
  color: #1a2980;
  background: #e3f2fd;
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border-radius: 6px 6px 0 0;
}

.mapping-title i {
  margin-right: 12px;
  font-size: 1.3rem;
  color: #4286f4;
}

.mapping-content {
  flex: 1;
  overflow-y: auto;
  padding: 12px;
}

/* 更紧凑的表映射行 */
.mapping-row {
  display: flex;
  align-items: center;
  padding: 10px;
  margin: 8px 0;
  border-radius: 6px;
  background: white;
  box-shadow: 0 1px 6px rgba(0,0,0,0.03);
  border: 1px solid #eaeaea;
  transition: all 0.3s;
  cursor: pointer;
  position: relative;
  height: 80px; /* 增加高度适应多行标签 */
}

.mapping-row:hover {
  box-shadow: 0 2px 10px rgba(66, 134, 244, 0.15);
}

.mapping-row.active {
  border-left: 3px solid #4286f4;
  background-color: #f5f9ff;
}

.row-number {
  width: 32px;
  height: 32px;
  background: #4286f4;
  color: white;
  font-size: 1.1rem;
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  margin-right: 12px;
  flex-shrink: 0;
}

/* 字段容器 */
.field-box {
  flex: 1;
  min-height: 56px;
  border-radius: 6px;
  padding: 10px;
  margin: 0 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px dashed transparent;
  transition: all 0.3s;
}

.field-box.drag-over {
  background: rgba(66, 134, 244, 0.1);
  border-color: #4286f4;
}

.source-field {
  border-color: rgba(66, 134, 244, 0.2);
  background: rgba(66, 134, 244, 0.03);
}

.target-field {
  border-color: rgba(67, 206, 162, 0.2);
  background: rgba(67, 206, 162, 0.03);
}

.tag {
  padding: 8px 16px;
  border-radius: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 120px;
}

.source-tag {
  background: #e3f2fd;
  border: 1px solid #4286f4;
  color: #1a2980;
}

.target-tag {
  background: #e8f9f3;
  border: 1px solid #43cea2;
  color: #165c48;
}

.arrow-icon {
  font-size: 1.2rem;
  color: #999;
  flex-shrink: 0;
}

.remove-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #f8fafc;
  border: 1px solid #e1e8f0;
  color: #ff5252;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: 8px;
  flex-shrink: 0;
  cursor: pointer;
  transition: all 0.3s;
}

.remove-btn:hover {
  background: #ffe5e5;
  border-color: #ffb8b8;
}

.template-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 90px;
  border: 2px dashed #d1e0e9;
  border-radius: 6px;
  margin: 8px 0;
  cursor: pointer;
  transition: all 0.3s;
  color: #999;
}

.template-row:hover {
  border-color: #4286f4;
  color: #4286f4;
  background: #f5f9ff;
}

.template-row i {
  font-size: 1.8rem;
  margin-bottom: 8px;
}

.field-type {
  margin-left: 8px;
  font-size: 0.85rem;
  color: #777;
  background: #f5f7fa;
  padding: 2px 6px;
  border-radius: 4px;
}

/* 字段映射区域 */
.field-mapping-container {
  display: flex;
  flex: 1;
  overflow: hidden;
}

.field-mapping-center {
  width: 100%;
  display: flex;
  flex-direction: column;
}

.field-mapping-content {
  flex: 1;
  overflow-y: auto;
  padding: 12px;
}

.field-type-label {
  margin-left: 8px;
  font-size: 0.85rem;
  color: #777;
  background: #f5f7fa;
  padding: 2px 8px;
  border-radius: 4px;
}

.field-status-icon {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: 8px;
}

.field-status-good {
  background: rgba(67, 206, 162, 0.15);
  color: #43cea2;
}

.field-status-warning {
  background: rgba(255, 183, 77, 0.15);
  color: #ffb74d;
}

.field-status-error {
  background: rgba(255, 82, 82, 0.15);
  color: #ff5252;
}

/* 字段映射项 */
.field-mapping-item {
  display: flex;
  align-items: center;
  padding: 8px;
  margin: 8px 0;
  border-radius: 6px;
  background: white;
  box-shadow: 0 1px 4px rgba(0,0,0,0.03);
  border: 1px solid #eaeaea;
  transition: all 0.3s;
}

.field-mapping-item:hover {
  box-shadow: 0 2px 8px rgba(66, 134, 244, 0.15);
}

/* 添加目标表名样式 */
.target-table-name {
  font-weight: bold;
  margin-bottom: 5px;
  color: rgba(84, 243, 172, 0.99);
  align-items: center;
}

.target-table-name i {
  margin-right: 6px;
  color: #43cea2;
}

/* Join配置区域样式 */
.join-config-section {
  background: white;
  border-radius: 8px;
  margin-top: 15px;
  padding: 15px;
  border: 1px solid #eaeaea;
  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}

.join-config-title {
  font-size: 1.1rem;
  font-weight: 500;
  margin-bottom: 15px;
  color: #1a2980;
  display: flex;
  align-items: center;
}

.join-config-title i {
  margin-right: 10px;
  color: #4286f4;
}

.join-config-item {
  padding: 12px;
  margin-bottom: 15px;
  border-radius: 6px;
  background: #f8fafc;
  border: 1px solid #e1e8f0;
}

.table-selectors {
  display: flex;
  gap: 10px;
  margin-bottom: 12px;
  align-items: center;
}

.field-selectors {
  display: flex;
  gap: 10px;
  align-items: center;
}

.join-type-select {
  width: 140px;
}

.join-equal {
  font-size: 1.2rem;
  font-weight: bold;
  color: #5c6b80;
}

.remove-join-btn {
  background: none;
  border: none;
  color: #ff6b6b;
  cursor: pointer;
  padding: 5px;
  margin-left: 5px;
}

.remove-join-btn:hover {
  color: #ff5252;
}

.add-join-btn {
  padding: 8px 15px;
  background: #e3f2fd;
  border: 1px solid #4286f4;
  color: #4286f4;
  border-radius: 4px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  font-size: 0.95rem;
  transition: all 0.3s;
}

.add-join-btn:hover {
  background: #d1e8ff;
}

.add-join-btn i {
  margin-right: 5px;
}

/* 新增：关联图标样式 */
.join-icon {
  margin-left: 10px;
  margin-right: 5px;
  color: #c0c4cc; /* 默认灰色 */
  font-size: 18px;
  vertical-align: middle;
  transition: color 0.3s;
}

.join-icon.has-join {
  color: #4286f4; /* 有关联时蓝色 */
}

/* 调整标签容器布局 */
.tags-container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center; /* 垂直居中 */
}

/* 调整源表标签布局 */
.tag.source-tag {
  display: flex;
  align-items: center;
  position: relative;
}
</style>
